package com.hyt.it.ogt.ykcj.service.grade;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hyt.it.ogt.ykcj.common.constant.Constants;
import com.hyt.it.ogt.ykcj.common.constant.ImportFieldConstants;
import com.hyt.it.ogt.ykcj.common.core.domain.AjaxResult;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.common.utils.poi.ExcelUtil;
import com.hyt.it.ogt.ykcj.domain.exam.ExamSubjectInfo;
import com.hyt.it.ogt.ykcj.domain.vo.ExamindeGradeInfoRsp;
import com.hyt.it.ogt.ykcj.domain.vo.ExamineeSubjectGradeInfoVo;

/**
 * @Author chentb
 * @Date 2021/7/1 15:36
 */

public class ExportUtils {

    private static final Logger log = LoggerFactory.getLogger(ExportUtils.class);

    public static AjaxResult doExport(List<ExamindeGradeInfoRsp> dataList, String sheetName,List<ExamSubjectInfo> examSubjectList){
        List<String> headerList =getHeaderName(ImportFieldConstants.getGradeFieldMap(),ImportFieldConstants.getSubjectGradeFieldMap(),examSubjectList.size());
        return ExportUtils.exportData(headerList,dataList,examSubjectList,sheetName);
    }

    /**
     * 设置导出的标题
     * @return
     */
    public static List<String> getHeaderName(Map<String,String> fatherMap,Map<String,String> childMap,int childSize){
        List<String> headerNameList = new ArrayList<>();
        if (null != fatherMap){
            for (Map.Entry<String,String> entry:fatherMap.entrySet()){
                headerNameList.add(entry.getKey());
            }
        }

        if (null != childMap){
            for (Map.Entry<String,String> entry:childMap.entrySet()){
                for (int i=1;i<=childSize;i++){
                    if (entry.getKey().lastIndexOf(Constants.splitStr) < 0){
                        headerNameList.add(entry.getKey()+i);
                    }else {
                        headerNameList.add(entry.getKey()+i);
                    }

                }
            }

        }
        return headerNameList;
    }

    public static List<String> getHeaderName(Map<String,String> fatherMap,Map<String,String> childMap,List<String> subjectCodelist){
        List<String> headerNameList = new ArrayList<>();
        if (null != fatherMap){
            for (Map.Entry<String,String> entry:fatherMap.entrySet()){
                headerNameList.add(entry.getKey());
            }
        }

        if (null != childMap){
            for (Map.Entry<String,String> entry:childMap.entrySet()){
                for (int i=0;i<subjectCodelist.size();i++){
                    if (entry.getKey().lastIndexOf(Constants.splitStr) < 0){
                        headerNameList.add(entry.getKey()+subjectCodelist.get(i).substring(2));
                    }else {
                        headerNameList.add(entry.getKey()+subjectCodelist.get(i).substring(2));
                    }

                }
            }

        }
        return headerNameList;
    }


    public static AjaxResult exportData(List<String> list, List<ExamindeGradeInfoRsp> dataList,List<ExamSubjectInfo> examSubjectList,String sheetName){
        // 科目数量
        int subjectNum = examSubjectList.size();
        FileOutputStream os = null;
        SXSSFWorkbook sxssfWorkbook = null;
        try {
            // 获取SXSSFWorkbook
            sxssfWorkbook = new SXSSFWorkbook();
            Sheet sheet = sxssfWorkbook.createSheet("Sheet1");
            // 冻结第一行
            sheet.createFreezePane(0, 1);
            // 创建第一行,作为header表头
            Row header = sheet.createRow(0);
            // 循环创建header单元格
            for (int cellnum = 0; cellnum < list.size(); cellnum++) {
                Cell cell = header.createCell(cellnum);
                cell.setCellValue(list.get(cellnum));
                //设置每列固定宽度
                sheet.setColumnWidth(cellnum, 10 * 256);
            }
            // execl导出考试成绩相关字段属性
            Map<String,Field> gradeInfoMap = getAllFields(new ExamindeGradeInfoRsp());
            // execl导出考试成绩相关字段属性
            Map<String,Field> subjectInfoMap = getAllFields(new ExamineeSubjectGradeInfoVo());

            // execl中考试成绩相关字段属性
            Map<String, String> gradeFieldMap = ImportFieldConstants.getGradeFieldMap();
            // execl中考试科目成绩相关字段属性
            Map<String, String> subjectFieldMap = ImportFieldConstants.getSubjectGradeFieldMap();
            // 遍历创建行,导出数据
            for (int rownum = 0; rownum < dataList.size(); rownum++) {
                Row row = sheet.createRow(rownum+1);
                ExamindeGradeInfoRsp rsp = dataList.get(rownum);
                // 判断是否需要重新获取类的所有属性

                // 循环创建单元格
                for (int cellnum = 0; cellnum < list.size(); cellnum++) {
                    Cell cell = row.createCell(cellnum);
                    String fiedlName = list.get(cellnum);
                    System.out.println(fiedlName);
                    // 考生属性
                    if (null != gradeFieldMap.get(fiedlName)){
                        Field field =  gradeInfoMap.get(gradeFieldMap.get(fiedlName));
                        field.setAccessible(true);
                        System.out.println(field.get(rsp));
                        if(null != field.get(rsp)){
                            cell.setCellValue(field.get(rsp).toString());
                        }else {
                            cell.setCellValue("");
                        }

                    }else {// 科目属性
                        // 遍历科目列表
                        List<ExamineeSubjectGradeInfoVo> subjectGradeList = rsp.getSubjectGradeList();
                        Map<String,ExamineeSubjectGradeInfoVo> subjectGradeInfoMap = subjectGradeList.stream().collect(Collectors.toMap(ExamineeSubjectGradeInfoVo::getSubjectId,
                                examSubjectInfo -> examSubjectInfo));
                        for (int i=1;i<=subjectNum;i++){
                            // 无法通过科目后缀分隔则认为不匹配
                            if (fiedlName.endsWith(String.valueOf(i))){
                                // 获取当前科目对应的科目id
                                String subjectId = examSubjectList.get(i-1).getId();
                                // 健值
                                String mapKey=null;
                                // 科目通过年份
                                int ch = fiedlName.lastIndexOf(Constants.splitStr);
                                if (ch == -1){
                                    mapKey ="PASS";
                                }else {
                                    String[] arr = fiedlName.split(Constants.splitStr);
                                    mapKey = arr[0]+Constants.splitStr;
                                }

                                // 有科目成绩列表
                                if (CollectionUtils.isNotEmpty(subjectGradeList)){
                                    // 校验具体哪个科目有数据
                                    //for (ExamineeSubjectGradeInfoVo vo:subjectGradeList) {
                                        if (null != subjectGradeInfoMap.get(subjectId)){
                                            ExamineeSubjectGradeInfoVo vo = subjectGradeInfoMap.get(subjectId);
                                            Field field = subjectInfoMap.get(subjectFieldMap.get(mapKey));
                                            field.setAccessible(true);
                                            System.out.println(field.get(vo));
                                            if (null != field.get(vo)){

                                                // 科目需要转换成名字
                                                if (ImportAbstractService.PREFIX_KM.equals(mapKey)){
                                                    // 不为空则改名字已被用过。直接跳过
                                                    cell.setCellValue(vo.getSubjectName());

                                                }else {
                                                    cell.setCellValue(field.get(vo).toString());
                                                }
                                            }else {
                                                cell.setCellValue("");
                                            }
                                            break;
                                        }
                                    //}

                                }else {
                                    cell.setCellValue("");
                                }
                            }

                        }
                    }
                }
            }

            String filename = ExcelUtil.encodingFilename(sheetName);
            os = new FileOutputStream(ExcelUtil.getAbsoluteFile(filename));
            sxssfWorkbook.write(os);
            return AjaxResult.success(filename);
        } catch (Exception e)
        {
            log.error("导出Excel异常{}", e.getMessage());
            throw new CustomException("导出Excel失败，请联系管理员！");
        }
        finally
        {
            if (sxssfWorkbook != null)
            {
                try
                {
                    sxssfWorkbook.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (os != null)
            {
                try
                {
                    os.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }

    }


    /**
     * 获取子类和父类的所有属性字段
     * @param object
     * @return
     */
    public static Map<String,Field> getAllFields(Object object){
        Class clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        Map<String,Field> fieldMap = fieldList.stream().collect(Collectors.toMap(Field::getName,field -> field,(key1 , key2)-> key2));
        return fieldMap;
    }

    public static AjaxResult downloadTemplate(Map<String,String> fatherMap,Map<String,String> childMap,List<String> subjectCodeList){
        List<String> list  = getHeaderName(fatherMap,childMap,subjectCodeList);
        // 科目数量
        FileOutputStream os = null;
        SXSSFWorkbook sxssfWorkbook = null;
        try {
            // 获取SXSSFWorkbook
            sxssfWorkbook = new SXSSFWorkbook();
            Sheet sheet = sxssfWorkbook.createSheet("Sheet1");
            // 冻结第一行
            sheet.createFreezePane(0, 1);
            // 创建第一行,作为header表头
            Row header = sheet.createRow(0);
            // 循环创建header单元格
            for (int cellnum = 0; cellnum < list.size(); cellnum++) {
                Cell cell = header.createCell(cellnum);
                cell.setCellValue(list.get(cellnum));
                //设置每列固定宽度
                sheet.setColumnWidth(cellnum, 10 * 256);
            }

            String filename = ExcelUtil.encodingFilename("考试成绩模板");
            os = new FileOutputStream(ExcelUtil.getAbsoluteFile(filename));
            sxssfWorkbook.write(os);
            return AjaxResult.success(filename);
        } catch (Exception e)
        {
            log.error("导出Excel异常{}", e.getMessage());
            throw new CustomException("导出Excel失败，请联系管理员！");
        }
        finally
        {
            if (sxssfWorkbook != null)
            {
                try
                {
                    sxssfWorkbook.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (os != null)
            {
                try
                {
                    os.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static AjaxResult downloadTemplate(Map<String,String> fatherMap,Map<String,String> childMap,int subjectNum){
        List<String> list  = getHeaderName(fatherMap,childMap,subjectNum);
        // 科目数量
        FileOutputStream os = null;
        SXSSFWorkbook sxssfWorkbook = null;
        try {
            // 获取SXSSFWorkbook
            sxssfWorkbook = new SXSSFWorkbook();
            Sheet sheet = sxssfWorkbook.createSheet("Sheet1");
            // 冻结第一行
            sheet.createFreezePane(0, 1);
            // 创建第一行,作为header表头
            Row header = sheet.createRow(0);
            // 循环创建header单元格
            for (int cellnum = 0; cellnum < list.size(); cellnum++) {
                Cell cell = header.createCell(cellnum);
                cell.setCellValue(list.get(cellnum));
                //设置每列固定宽度
                sheet.setColumnWidth(cellnum, 10 * 256);
            }

            String filename = ExcelUtil.encodingFilename("考试成绩模板");
            os = new FileOutputStream(ExcelUtil.getAbsoluteFile(filename));
            sxssfWorkbook.write(os);
            return AjaxResult.success(filename);
        } catch (Exception e)
        {
            log.error("导出Excel异常{}", e.getMessage());
            throw new CustomException("导出Excel失败，请联系管理员！");
        }
        finally
        {
            if (sxssfWorkbook != null)
            {
                try
                {
                    sxssfWorkbook.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (os != null)
            {
                try
                {
                    os.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
    }


    /**
     * 制作导入职位模板
     * @param fieldMap
     * @return
     */
    public static AjaxResult downladTemplate(Map<String,String> fieldMap) {
        List<String> list = getHeaderName(fieldMap);
        SXSSFWorkbook sxssfWorkbook = null;
        FileOutputStream os = null;

        try{
            //获取sxssfWorkbook
            sxssfWorkbook = new SXSSFWorkbook();
            //创建sheet
            Sheet sheet = sxssfWorkbook.createSheet("sheet1");
            //冻结第一行
            sheet.createFreezePane(0,1);
            //创建表头
            Row header = sheet.createRow(0);

            //循环创建header单元格
            for(int cellnum = 0;cellnum<list.size();cellnum++)
            {
                Cell cell = header.createCell(cellnum);
                cell.setCellValue(list.get(cellnum));
                //设置单元格宽度
                sheet.setColumnWidth(cellnum,10 * 256);
            }

            String fieldName = ExcelUtil.encodingFilename("公务员考试职位模板");
            os = new FileOutputStream(ExcelUtil.getAbsoluteFile(fieldName));
            sxssfWorkbook.write(os);
            return AjaxResult.success(fieldName);
        }catch (Exception e){
            log.info("导出Excel异常{}",e.getMessage());
            throw new CustomException("导出Excel失败，请联系管理员");
        }finally
        {
            if (null != os) {
                try
                {
                    os.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (null != sxssfWorkbook){
                try
                {
                    sxssfWorkbook.close();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

    public static List<String> getHeaderName(Map<String,String> map)
    {
        List<String> headNameList = new ArrayList<>();
        if (null != map)
        {
            for (Map.Entry<String,String> entry : map.entrySet())
                headNameList.add(entry.getKey());
        }
        return headNameList;
    }

    /**
     * 下载导入模板文件
     *
     * @param fileName 文件名称
     * @param sheetName 工作表名称
     * @param pageSize 单页最大行数
     * @param titles 表头
     * @param keys 字段名
     * @param recordList 数据集
     * @return 模板文件
     */
    public static String exportExcelTemplate(String fileName, String sheetName, int pageSize, List<String> titles, List<String> keys, List<Map<String, String>> recordList) {
        Map<Integer, Integer> maxWidth = new HashMap<>(); // 存储最大列宽
        SXSSFWorkbook workBook = new SXSSFWorkbook();
        Sheet sheet = null;
        int sheetCount = (int) Math.ceil(Double.valueOf(recordList.size()) / pageSize);
        if (sheetCount == 0) {
            sheet = workBook.createSheet(sheetName);
            Row headRow = sheet.createRow(0);
            Cell cell = null;
            if (titles != null) {
                for (int i = 0; i < titles.size(); i++) {
                    cell = headRow.createCell(i);
                    cell.setCellValue(titles.get(i));
                    maxWidth.put(i, cell.getStringCellValue().getBytes().length * 256);
                }
            }
        }
        for (int i = 0; i < sheetCount; i++) {
            sheet = workBook.createSheet((i == 0) ? sheetName : (sheetName + "(" + (i + 1) + ")"));
            // 设置第一行表头的各个列标题
            Row headRow = sheet.createRow(0);
            Cell cell = null;
            if (titles != null) {
                for (int j = 0; j < titles.size(); j++) {
                    cell = headRow.createCell(j);
                    cell.setCellValue(titles.get(j));
                    maxWidth.put(j, cell.getStringCellValue().getBytes().length * 256);
                }
            }
            // 设置第二行开始的动态列数据
            if (recordList != null) {
                int start = i * pageSize;
                int end = (i + 1) * pageSize;
                end = end > recordList.size() ? recordList.size() : end;
                for (int j = start, row = 1; j < end; j++, row++) {
                    Row bodyRow = sheet.createRow(row);
                    Map<String, String> record = recordList.get(j);
                    for (int k = 0; k < keys.size(); k++) {
                        cell = bodyRow.createCell(k);
                        String s = (record.get(keys.get(k)) == null || record.get(keys.get(k)).equals("null")) ? "":record.get(keys.get(k));
                        cell.setCellValue(s);
                        int length = cell.getStringCellValue().getBytes().length * 256;
                        //这里把宽度最大限制到15000
                        if (length > 15000) {
                            length = 15000;
                        }
                        maxWidth.put(k, Math.max(length, maxWidth.get(k)));
                    }
                }
            }
        }
        if(titles != null){
            for (int j = 0; j < titles.size(); j++) {
                sheet.setColumnWidth(j, maxWidth.get(j));
            }
        }

        fileName = ExcelUtil.encodingFilename(fileName);
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(ExcelUtil.getAbsoluteFile(fileName));
            workBook.write(os);
            return fileName;
        } catch (IOException e) {
            e.printStackTrace();
            log.error("导出Excel异常{}", e.getMessage());
            throw new CustomException("导出Excel失败，请联系管理员！");
        } finally {
            if (workBook != null) {
                try {
                    workBook.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
